/** @file
 * Copyright (c) 2016-2018, 2021, 2023, Arm Limited or its affiliates. All rights reserved.
 * SPDX-License-Identifier : Apache-2.0

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

#include "val/include/bsa_acs_val.h"
#include "val/include/val_interface.h"

#include "val/include/bsa_acs_iovirt.h"

#define TEST_NUM   (ACS_PCIE_TEST_NUM_BASE + 40)
#define TEST_RULE  "PCI_IC_11"
#define TEST_DESC  "PCIe RC,HART - Same Inr Shareable Domain"

#define INNER_SHAREABLE 1

static void
payload(void)
{
  uint32_t num_pcie_rc;
  uint32_t mem_attr;
  uint32_t index = val_hart_get_index_mpid (val_hart_get_mpid());

  num_pcie_rc = val_iovirt_get_pcie_rc_info(NUM_PCIE_RC, 0);

  if (!num_pcie_rc) {
     val_print(ACS_PRINT_DEBUG, "\n       Skip because no PCIe RC detected  ", 0);
     val_set_status(index, RESULT_SKIP(TEST_NUM, 1));
     return;
  }

  while (num_pcie_rc) {
      num_pcie_rc--;   // Index is one lesser than the component number being accessed
      mem_attr = val_iovirt_get_pcie_rc_info(RC_MEM_ATTRIBUTE, num_pcie_rc);

      if (mem_attr == INNER_SHAREABLE)
         val_set_status(index, RESULT_PASS(TEST_NUM, 1));
      else {
         val_print(ACS_PRINT_ERR,
                 "\n       Failed mem attribute check for PCIe RC %d", num_pcie_rc);
         val_set_status(index, RESULT_FAIL(TEST_NUM, 1));
         return;
      }
  }

}

uint32_t
os_p040_entry(uint32_t num_hart)
{

  uint32_t status = ACS_STATUS_FAIL;

  num_hart = 1;  //This test is run on single processor

  status = val_initialize_test(TEST_NUM, TEST_DESC, num_hart);
  if (status != ACS_STATUS_SKIP)
      val_run_test_payload(TEST_NUM, num_hart, payload, 0);

  /* get the result from all HART and check for failure */
  status = val_check_for_error(TEST_NUM, num_hart, TEST_RULE);

  val_report_status(0, BSA_ACS_END(TEST_NUM), NULL);

  return status;
}
